package com.h819.core.file;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

/**
 * @ClassName: MyFileUtils
 * @Description: TODO(自定义的常用工具类)
 * @author h819
 * @date May 14, 2009 10:15:24 AM
 * @version V1.0 作为 commons io 类的补充，平时应用的时候，主要参考 commons io，其中没有解决方法的时候，再参考本类。另外
 *          jdk 6 添加了一些新的 io 操作方法，可以再次查看
 */

// org.apache.commons.io.FilenameUtils 中有一些文件名分隔符的有用的类，如separatorsToSystem 方法等

public class MyFileUtils {

	private static Logger log = Logger.getLogger(MyFileUtils.class);
	private static ArrayList<String> fileNames = null;

	/**
	 * 静态方法调用，不需要生成实例
	 */
	public MyFileUtils() {

	}

	/**
	 * 建立文件夹.如果文件夹不存在，创建；存在则略过。
	 * 
	 * 实现代码拷贝子 commons io FileUtils.forceMkdir(File directory) ，注意体会其实现方法。
	 * 
	 * @throws IOException
	 */
	public static void forceMkdir(File destDirectory) throws IOException {

		if (destDirectory.exists()) {
			if (!destDirectory.isDirectory()) {
				String message = "File " + destDirectory + " exists and is "
						+ "not a directory. Unable to create directory.";
				throw new IOException(message);
			}
		} else {
			if (!destDirectory.mkdirs()) {
				// Double-check that some other thread or process hasn't made
				// the directory in the background
				if (!destDirectory.isDirectory()) {
					String message = "Unable to create directory "
							+ destDirectory;
					throw new IOException(message);
				}
			}
		}
	}

	/**
	 * 得到给定目录的所有文件的绝对路径
	 * 
	 * @param desDirecry
	 *            指定的目录
	 * @param fileNameExtensionFilter
	 *            文件扩展名过滤器
	 * @return
	 * @throws IOException
	 */

	public static ArrayList<String> getFileNames(File desDirecry,
			MyFileNameExtensionFilter fileNameExtensionFilter)
			throws IOException {
		fileNames = new ArrayList<String>();
		getFileNamesList(desDirecry, fileNameExtensionFilter);
		return fileNames;
	}

	/**
	 * 找到给定目录的所有文件的绝对路径，并把结果放入全局变量。设置全局变量保存结果，而不是直接返回，是因为用了递归方法。
	 * 
	 * @param desDirecry
	 *            指定的目录
	 * @param fileNameExtensionFilter
	 *            文件扩展名过滤器
	 * @throws IOException
	 */
	private static void getFileNamesList(File desDirecry,
			MyFileNameExtensionFilter fileNameExtensionFilter)
			throws IOException {

		if (!desDirecry.isDirectory())
			return;

		File[] files;

		files = desDirecry.listFiles(fileNameExtensionFilter);

		// log.info("====");
		// for(File f : files)
		// log.info(f);

		for (File f : files) {
			if (f.isFile())
				fileNames.add(f.getAbsolutePath());
			if (f.isDirectory())
				getFileNamesList(f, fileNameExtensionFilter);
		}

	}

	/**
	 * windows 系统中，\ , / , : , * , ? , " , < , > , | 九个字符不能出现在文件夹中，用指定的字符代替。
	 * 
	 * @param filename
	 *            文件名称
	 * @param replacement
	 *            替代的字符串
	 * @return
	 */
	public static String getWindowsLegalFileName(String filename,
			String replacement) {

		filename = StringUtils.replace(filename, "\\", replacement);
		filename = StringUtils.replace(filename, "/", replacement);
		filename = StringUtils.replace(filename, ":", replacement);
		filename = StringUtils.replace(filename, "*", replacement);
		filename = StringUtils.replace(filename, "?", replacement);
		filename = StringUtils.replace(filename, "\"", replacement);
		filename = StringUtils.replace(filename, "<", replacement);
		filename = StringUtils.replace(filename, ">", replacement);
		filename = StringUtils.replace(filename, "|", replacement);

		return filename;

	}

	/**
	 * 拷贝 jar 资源中的文件到系统临时目录下
	 * 
	 * @param resourceNames
	 *            待拷贝的 jar 中的文件名称
	 *            <p>
	 *            参数写法
	 *            </p>
	 *            <p>
	 *            String[] resourceNames = new String[] { "/license.dat",
	 *            "/pdfdecrypt.exe", "/SkinMagic.dll" };
	 *            </p>
	 *            <p>
	 *            此时，文件必须在 jar 文件的根目录下面，且jar 需用 java 命令打包。
	 *            </p>
	 * 
	 * @param tempDir
	 *            为了容易查看，在系统临时目录下建立文件夹，存放拷贝后的文件
	 * @param callClass
	 *            调用跟方法的类名，定位资源文件位置用到
	 * @return 拷贝完成后，返回值中每个资源文件在数组中的位置顺序，和参数中该文件在数组中的位置顺序一致。
	 */
	public static String[] copyResourceFileFromJarLibToTmpDir(
			String[] resourceNames, String tempDir, Class callClass) {
		// 拷贝资源文件

		// 拷贝资源文件到临时目录
		// resources = new String[] { "/license.dat", "/pdfdecrypt.exe",
		// "/SkinMagic.dll" };
		String[] resourcePath = new String[resourceNames.length];

		InputStream is = null;
		for (int i = 0; i < resourceNames.length; i++) {

			// log.info("Resourcename name :" + resourceNames[i]);

			is = callClass.getClass().getResourceAsStream(resourceNames[i]);

			if (is == null) {
				log.info(resourceNames[i] + " not exist,has not jar liberary.");
				return null;
			}

			String tempfilepath = SystemUtils.getJavaIoTmpDir()
					+ File.separator + tempDir + File.separator
					+ resourceNames[i];

			log.info("resource copy to :" + tempfilepath);

			File f = new File(tempfilepath);
			
			// 资源文件一般都比较小，为了得到最新的文件版本，覆盖拷贝
			try {
				// 拷贝资源文件到临时文件夹
				FileUtils.copyInputStreamToFile(is, new File(tempfilepath));

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}

			resourcePath[i] = tempfilepath;

		}// 资源文件拷贝完毕

		// for (String s : resourcePath)
		// log.info(s);

		return resourcePath;
	}

	/**
	 * 测试 copyResourceFileFromJarLibToTmpDir 方法
	 */
	private void testCopyResourceFileFromJarLibToTmpDir() {

		String[] resources = new String[] { "/license.dat", "/pdfdecrypt.exe",
				"/SkinMagic.dll" };

		copyResourceFileFromJarLibToTmpDir(resources, "tempdir",
				MyFileUtils.class);
	}

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub

		// Windows下路径分隔符是"\"
		// Unix与Linux下路径分隔符是"/"
		// *****如果路径分隔符用File.separator表示，则可移植性更强。

		MyFileUtils mf = new MyFileUtils();

		// 测试拷贝文件
		mf.testCopyResourceFileFromJarLibToTmpDir();
	}

}
